package com.wq.app.painter.widget.gestures.creator;

import android.graphics.RectF;
import android.view.MotionEvent;

import com.wq.app.painter.data.Stroke;
import com.wq.app.painter.data.Stroke.StrokePoint;
import com.wq.app.painter.widget.StrokeConfig;


public class GestureCreator {
    private Stroke currStroke;
    private GestureCreatorListener delegate;
    private StrokeConfig config;
    private int lastX;
    private int lastY;
    private float scaleFactor = 1.0f;
    private RectF viewRect = new RectF();
    private RectF canvasRect = new RectF();
    private long prevTimestamp;

    public GestureCreator(GestureCreatorListener delegate) {
        this.delegate = delegate;
    }

    public void onTouchEvent(MotionEvent event) {
        int touchX = Math.round((event.getX() + viewRect.left) / scaleFactor);
        int touchY = Math.round((event.getY() + viewRect.top) / scaleFactor);

        //Log.d("Drawer", "T[" + touchX + "," + touchY + "] V[" + viewRect.toShortString() + "] S[" + scaleFactor + "]");
        long currTime = currTimestamp();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                actionDown(0, touchX, touchY);
                prevTimestamp = currTime;
                lastX = touchX;
                lastY = touchY;
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(touchX - lastX) >= StrokeConfig.TOUCH_TOLERANCE
                        || Math.abs(touchY - lastY) >= StrokeConfig.TOUCH_TOLERANCE) {
                    actionMove(currTime - prevTimestamp, touchX, touchY);
                    prevTimestamp = currTime;
                    lastX = touchX;
                    lastY = touchY;
                }
                break;
            case MotionEvent.ACTION_UP:
                actionUp(currTime - prevTimestamp, touchX, touchY);
                prevTimestamp = currTime;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                actionPointerDown();
                break;
        }
    }

    private void actionDown(long timestamp, int touchX, int touchY) {
        if (insideCanvas(touchX, touchY)) {
            int color = config != null ? config.getStrokeColor() : StrokeConfig.DEFAULT_FONT_COLOR;
            float width = config != null ? config.getStrokeWidth() : StrokeConfig.DEFAULT_FONT_WIDTH;
            currStroke = new Stroke(color, width);

            currStroke.addPoint(new StrokePoint(timestamp, touchX, touchY));
            delegate.onGestureCreated(currStroke);
            delegate.onCurrentGestureChanged(currStroke);
        }
    }

    private void actionMove(long timestamp, int touchX, int touchY) {
        if (currStroke != null) {
            currStroke.addPoint(new StrokePoint(timestamp, touchX, touchY));
        }
    }

    private void actionUp(long timestamp, int touchX, int touchY) {
        if (currStroke != null) {
            currStroke.addPoint(new StrokePoint(timestamp, touchX, touchY));
            delegate.onCurrentGestureChanged(null);
            currStroke = null;
        }
    }

    private void actionPointerDown() {
        currStroke = null;
        delegate.onCurrentGestureChanged(null);
    }

    private boolean insideCanvas(float touchX, float touchY) {
//        return canvasRect.contains(touchX, touchY);
        return true;
    }

    private long currTimestamp() {
        return System.currentTimeMillis();
    }

    public void setConfig(StrokeConfig config) {
        this.config = config;
    }

    public void onScaleChange(float scaleFactor) {
        this.scaleFactor = scaleFactor;
    }

    public void onViewPortChange(RectF viewRect) {
        this.viewRect = viewRect;
    }

    public void onCanvasChanged(RectF canvasRect) {
        this.canvasRect.right = canvasRect.right / scaleFactor;
        this.canvasRect.bottom = canvasRect.bottom / scaleFactor;
    }
}
